/*
 * Ingenic IMP ISPOSD solution.
 *
 * Copyright (C) 2015 Ingenic Semiconductor Co.,Ltd
 * Author: Jim <jim.wang@ingenic.com>
 */

#include <stdio.h>
#include <string.h>
#include <semaphore.h>
#include <math.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>

#include <imp/imp_log.h>
#include <imp/imp_osd.h>
#include <imp/isp_osd.h>
#include <constraints.h>
#include <imp/imp_utils.h>
#include <sys/time.h>

#include <system/system.h>
#include <system/group.h>
#include <system/device.h>
#include <system/vbm.h>
#include <system/imp_alloc.h>
#include <fifo.h>
//#include <video/framesource.h>
#include "jz_ipu_hal.h"
#include "osd_mem.h"
#ifdef DMALLOC
#include <imp/dmalloc.h>
#endif

//#define ISPOSDDBG

typedef struct IMPISPOSDNode{
	int 		  sensorNum;		/*sensor号，单摄时该值为0，详见IMPVI_NUM结构*/
	int           rAttrIndex; 		/**< handle对应的索引*/
	int 		  refcnt;	  		/**< 节点创建的计数，创建时+1，销毁时-1，初始化为0*/
	uint8_t		  oldshowflg;		/*内部使用，记录上一次设置ISPOSD的osd显示状态*/
	IMPIspOsdRngStat status;
	IMPISPOSDNode *prev;
	IMPISPOSDNode *next;
	IMPIspOsdAttrAsm stIspOsdAsm;	/**< 图片属性*/
}IMPISPOSDNode;

typedef struct {
	IMPISPOSDNode	*head;
	IMPISPOSDNode	*tail;
} IMPIspOsdRgnList;

typedef struct {
	//sem_t					semIspRgn;
	IMPIspOsdRgnList		freerlist;
	IMPIspOsdRgnList		busyrlist;
	IMPISPOSDNode			IspOsdNode[MAXISPOSDPIC];/**< ISP绘制OSD的相关属性*/
}IMPISPOSDChn;

typedef struct {
	sem_t					semIspRgn;
	IMPISPOSDChn			IspOsdChn[MAXSUPCHNMUN];
	mem_alloc_info_t*       isp_osd_mem;			 /**ISPOSD使用的内存管理*/
}IMPISPOSD;

#define TAG "ISPOSD"

IMPISPOSD *gpIspOsd;
IMPAlloc g_alloc_isposd;
#define OSD_ISP_BUF_SIZE (1)
static unsigned int g_isp_pool_size = OSD_ISP_BUF_SIZE;	/*用于ISPOSD的使用*/

#define ISPOSDMAX(a, b) (a > b ? a : b)
#define ISPOSDMIN(a, b) (a < b ? a : b)
IMPISPOSD *getIspOsd()
{
	return gpIspOsd;
}

static void setIspOsd(IMPISPOSD *osd)
{
	gpIspOsd = osd;
	return ;
}
void IspOsdAdjust_Pic(int chn,IMPIspOsdRgnList *pIspRgnList);

static IMPISPOSD *alloc_IspOsd(void)
{
	IMPISPOSD *pisposd = NULL;
	pisposd = malloc(sizeof(IMPISPOSD));
	memset(pisposd,0x0,sizeof(IMPISPOSD));

	memset(&g_alloc_isposd, 0, sizeof(g_alloc_isposd));
	if (IMP_Alloc(&g_alloc_isposd, g_isp_pool_size, "IspOsdMem") < 0) {
		IMP_LOG_ERR(TAG, "[%s][%d]IMP_Alloc(%d) failed\n",__func__,__LINE__,g_isp_pool_size);
		IMP_Free(&g_alloc_isposd, (void *)g_alloc_isposd.info.vaddr);
		return NULL;
	}
    pisposd->isp_osd_mem = OSD_mem_create((void*)g_alloc_isposd.info.vaddr, g_isp_pool_size);
    if (pisposd->isp_osd_mem == NULL) {
		IMP_LOG_ERR(TAG, "[%s][%d]OSD_mem_create failed\n",__func__,__LINE__);
		return NULL;
    }

	return pisposd;
}

static void free_Isposd(IMPISPOSD *pisposd)
{
	OSD_mem_destroy(pisposd->isp_osd_mem);
	IMP_Free(&g_alloc_isposd, (void *)g_alloc_isposd.info.vaddr);
	memset(&g_alloc_isposd, 0, sizeof(g_alloc_isposd));
	free(pisposd);
	return ;
}

static int IspOsd_rgnsize(IMPIspOsdAttrAsm *pIspOsdNode)
{
	int size = 0;
	int stride = 0,height = 0;
	if (NULL == pIspOsdNode) {
		IMP_LOG_ERR(TAG, "[%s][%d] pIspOsdNode is null,check param!\n", __func__, __LINE__);
		return -1;
	}
	stride = pIspOsdNode->stsinglepicAttr.pic.osd_stride;
	height = pIspOsdNode->stsinglepicAttr.pic.osd_height;
	if(stride <= 0 || height <= 0) {
		IMP_LOG_ERR(TAG, "[%s][%d] stride(%d) height(%d) is invalid,check!\n", __func__, __LINE__,stride,height);
		return -1;
	}
	size = stride*height;
	//printf("rgn size:%d,height:%d,stride:%d\n",size ,pIspOsdNode->stsinglepicAttr.pic.osd_height,pIspOsdNode->stsinglepicAttr.pic.osd_stride);
	return size;
}

int IMP_OSD_SetPoolSize_ISP(int size)
{
	if(size <= 0) {
		IMP_LOG_ERR(TAG, "[%s][%d]IMP_OSD_SetPoolSize_ISP failed,size:%d!\n",__func__,__LINE__,size);
		return -1;
	}
	g_isp_pool_size = size;
	IMP_LOG_ERR(TAG, "[%s][%d]	IMP_OSD_SetPoolSize_ISP,size:%d\n", __func__, __LINE__, size);
	return 0;
}

int IMP_OSD_Init_ISP(void)
{
	int i = 0,j = 0;
	IMPISPOSD *pIsosd = alloc_IspOsd();
	if (pIsosd == NULL) {
		IMP_LOG_ERR(TAG, "alloc_IspOsd failed!\n");
		return -1;
	}

	if (sem_init(&pIsosd->semIspRgn, 0, 1) < 0) {
		IMP_LOG_ERR(TAG, "sem_init osd->registerlock failed!\n");
		return -1;
	}

	/*一共两个通道，每个通道最多8个区域块*/
	for(i = 0;i < MAXSUPCHNMUN;i++){
		for (j = 0; j < MAXISPOSDPIC; j++) {
			pIsosd->IspOsdChn[i].IspOsdNode[j].rAttrIndex = j;
			if (j == 0) {
				pIsosd->IspOsdChn[i].freerlist.head = pIsosd->IspOsdChn[i].freerlist.tail = &pIsosd->IspOsdChn[i].IspOsdNode[0];
				pIsosd->IspOsdChn[i].freerlist.tail->prev = NULL;
				pIsosd->IspOsdChn[i].freerlist.tail->next = NULL;
			} else {
				pIsosd->IspOsdChn[i].freerlist.tail->next = &pIsosd->IspOsdChn[i].IspOsdNode[j];
				pIsosd->IspOsdChn[i].freerlist.tail->next->prev = pIsosd->IspOsdChn[i].freerlist.tail;
				pIsosd->IspOsdChn[i].freerlist.tail = pIsosd->IspOsdChn[i].freerlist.tail->next;
				pIsosd->IspOsdChn[i].freerlist.tail->next = NULL;
			}
		}
	}

	setIspOsd(pIsosd);
	IMP_LOG_INFO(TAG, "isp osd init succeed!\n");
	return 0;
}
void IMP_OSD_Exit_ISP(void)
{
	IMPISPOSD *pIsposd = getIspOsd();
	if(NULL == pIsposd) {
		IMP_LOG_ERR(TAG, "[%s][%d], pIsposd is null,resource has been destroyed\n", __func__,__LINE__);
		return;
	}
	sem_destroy(&pIsposd->semIspRgn);
	free_Isposd(pIsposd);
	setIspOsd(NULL);
	return ;
}
void* isposd_mem_vir_to_phy(void* vaddr)
{
    void* paddr = (void *)((uint32_t)vaddr - g_alloc_isposd.info.vaddr + g_alloc_isposd.info.paddr);
    return paddr;
}

int IMP_OSD_CreateRgn_ISP(int chn,IMPIspOsdAttrAsm *pIspOsdAttr)
{
	if(chn < 0 || chn > 1) {
		IMP_LOG_ERR(TAG, "[%s][%d] IMP_OSD_CreateRgn_ISP chn is invalid\n", __func__, __LINE__, chn);
		return -1;
	}
	if(NULL != pIspOsdAttr) {
		IMP_LOG_ERR(TAG, "[%s][%d]pIspOsdAttr is not null,not support yet.\n", __func__, __LINE__);
		return -1;
	}

	IMPISPOSDNode *pIspOsdNode = NULL;
	IMPISPOSD *pIsposd = getIspOsd();
	if(NULL == pIsposd) {
		IMP_LOG_ERR(TAG, "[%s][%d], pIsposd is null,resource has been destroyed\n", __func__,__LINE__);
		return -1;
	}

	sem_wait(&pIsposd->semIspRgn);
	if (pIsposd->IspOsdChn[chn].freerlist.head == NULL) {
		sem_post(&pIsposd->semIspRgn);
		IMP_LOG_ERR(TAG, "pIsposd->IspOsdChn[chn].freerlist.head is empty,chn %d only support %d pic\n",chn,MAXISPOSDPIC);
		return -1;
	}
	pIspOsdNode = pIsposd->IspOsdChn[chn].freerlist.head;
	pIsposd->IspOsdChn[chn].freerlist.head = pIsposd->IspOsdChn[chn].freerlist.head->next;

	if (pIsposd->IspOsdChn[chn].freerlist.head == NULL) {
		pIsposd->IspOsdChn[chn].freerlist.tail = NULL;
	} else {
		pIsposd->IspOsdChn[chn].freerlist.head->prev = NULL;
	}

	if (pIsposd->IspOsdChn[chn].busyrlist.head == NULL) {
		pIsposd->IspOsdChn[chn].busyrlist.head = pIsposd->IspOsdChn[chn].busyrlist.tail = pIspOsdNode;
		pIsposd->IspOsdChn[chn].busyrlist.tail->prev = NULL;
		pIsposd->IspOsdChn[chn].busyrlist.tail->next = NULL;
	} else {
		pIsposd->IspOsdChn[chn].busyrlist.tail->next = pIspOsdNode;
		pIsposd->IspOsdChn[chn].busyrlist.tail->next->prev = pIsposd->IspOsdChn[chn].busyrlist.tail;
		pIsposd->IspOsdChn[chn].busyrlist.tail = pIsposd->IspOsdChn[chn].busyrlist.tail->next;
		pIsposd->IspOsdChn[chn].busyrlist.tail->next = NULL;
	}

	pIspOsdNode->status = IMP_ISP_OSD_RGN_BUSY;
	pIspOsdNode->refcnt += 1;

	IMP_LOG_DBG(TAG, "[%s][%d] chn%d handle%d success\n", __func__, __LINE__, chn,pIspOsdNode->rAttrIndex);

	sem_post(&pIsposd->semIspRgn);

	return pIspOsdNode->rAttrIndex;
}

void ISPOSD_RmemSetNewAddr(IMPISPOSDNode * pRgnheadnode,mem_node_t* pmheadnode)
{
    IMPISPOSDNode * pnode = NULL;
    mem_node_t*   pmemnode = NULL;
    pnode = pRgnheadnode;
    pmemnode = pmheadnode;
#if 1
    while(pmemnode){
		pnode = pRgnheadnode;/*每个小循环遍历完后应该要从小循环头开始遍历*/
        while(pnode) {
			/*IMP_LOG_ERR(TAG, "[%s][%d] IMPISPOSDNode->addr:%p,pnodeoldaddr:%p,pnodeaddr:%p\n", __func__,__LINE__,pnode->stIspOsdAsm.stsinglepicAttr.pic.osd_image,\
				pmemnode->oldaddr,pmemnode->addr);*/
            if(pnode->stIspOsdAsm.stsinglepicAttr.pic.osd_image == pmemnode->oldaddr){
                pnode->stIspOsdAsm.stsinglepicAttr.pic.osd_image = pmemnode->addr;
                pmemnode->oldaddr = pmemnode->addr;
                //pmemnode->list->meminfo->brmemsetbak = 1;
                break;
            }
            pnode = pnode->next;
        }
        pmemnode = pmemnode->next;
    }
#endif
#if 0
	while(pnode) {
		while(pmemnode) {
			IMP_LOG_ERR(TAG, "[%s][%d] IMPISPOSDNode->addr:%p,pnodeoldaddr:%p,pnodeaddr:%p\n", __func__,__LINE__,pnode->stIspOsdAsm.stsinglepicAttr.pic.osd_image,\
				pmemnode->oldaddr,pmemnode->addr);
			if(pnode->stIspOsdAsm.stsinglepicAttr.pic.osd_image == pmemnode->oldaddr) {
				pnode->stIspOsdAsm.stsinglepicAttr.pic.osd_image = pmemnode->addr;
                pmemnode->oldaddr = pmemnode->addr;
                break;
			}
			pmemnode = pmemnode->next;
		}
		pnode = pnode->next;
		pmemnode = pmheadnode;/*为了解决为pRgnheadnode中元素addr为NULL的情况，从而遍历不到整个链表，但是为什么会出现addr为NULL？*/
	}
	pnode = pRgnheadnode;
	while(pnode) {
		IMP_LOG_ERR(TAG, "[%s][%d] ~~~~IMPISPOSDNode->addr:%p\n", __func__,__LINE__,pnode->stIspOsdAsm.stsinglepicAttr.pic.osd_image);
		pnode = pnode->next;
	}
	IMP_LOG_ERR(TAG, "[%s][%d]:\n", __func__,__LINE__);
#endif

    return ;
}
/*通知ISPOSD 因为地址回溯修改，对应的节点rmem内存已经发生变化，需要修改*/
void OsdnotifyIsp(IMPISPOSDNode * pIspOsdhnode)
{
	int ret = 0;
	IMPISPOSDNode * pnode = NULL;
	pnode = pIspOsdhnode;
	void *vaddr = NULL,*paddr = NULL;

	while(pnode) {
		/*上一次是show是使能的，则地址回溯后立即通知ISP，否则因为地址改变，osd花屏*/
		if(pnode->rAttrIndex == pnode->stIspOsdAsm.stsinglepicAttr.pic.pinum)
		{
			vaddr = pnode->stIspOsdAsm.stsinglepicAttr.pic.osd_image;
			paddr = isposd_mem_vir_to_phy(vaddr);
			pnode->stIspOsdAsm.stsinglepicAttr.pic.osd_image = paddr;//ISP需要使用物理地址，因此转化
#if 1
			if(((uint32_t)paddr &(~0x7)) != (uint32_t)paddr){
				printf("[%s][%d]##################pData:%p is not 8 align,handl%d####################\n",__func__,__LINE__,paddr,pnode->rAttrIndex);
			}
			if((uint32_t)paddr < 0x100000){
				printf("[%s][%d]@@@@@@@@@@@@@@@@@@pData:%p addr is < 1M @@@@@@@@@@@@@@@@@@@@@@@@@@\n",__func__,__LINE__,paddr);
			}
#endif
#if 1
			if(0 == pnode->stIspOsdAsm.stsinglepicAttr.sensornum) {
				ret = IMP_ISP_Tuning_SetOSDAttr(&pnode->stIspOsdAsm.stsinglepicAttr.chnOSDAttr);
				if(ret < 0) {
					IMP_LOG_ERR(TAG, "[%s][%d]	IMP_ISP_Tuning_SetOSDAttr err!!!\n", __func__, __LINE__);
					return ;
				}

				ret = IMP_ISP_Tuning_SetOSDBlock(&pnode->stIspOsdAsm.stsinglepicAttr.pic);
				if(ret < 0) {
					IMP_LOG_ERR(TAG, "[%s][%d]	IMP_ISP_Tuning_SetOSDBlock err!!!\n", __func__, __LINE__);
					return ;
				}
			} else if(1 == pnode->stIspOsdAsm.stsinglepicAttr.sensornum){
				ret = IMP_ISP_Tuning_SetOSDAttr_Sec(&pnode->stIspOsdAsm.stsinglepicAttr.chnOSDAttr);
				if(ret < 0) {
					IMP_LOG_ERR(TAG, "[%s][%d]	IMP_ISP_Tuning_SetOSDAttr err!!!\n", __func__, __LINE__);
					return ;
				}

				ret = IMP_ISP_Tuning_SetOSDBlock_Sec(&pnode->stIspOsdAsm.stsinglepicAttr.pic);
				if(ret < 0) {
					IMP_LOG_ERR(TAG, "[%s][%d]	IMP_ISP_Tuning_SetOSDBlock err!!!\n", __func__, __LINE__);
					return ;
				}
			} else {
				IMP_LOG_ERR(TAG, "Sensornum Error!!! Current Sensornum is %d\n", pnode->stIspOsdAsm.stsinglepicAttr.sensornum);
			}
#endif
			pnode->stIspOsdAsm.stsinglepicAttr.pic.osd_image = vaddr;
		}
		pnode = pnode->next;
	}
	return;
}

int IMP_OSD_SetRgnAttr_PicISP(int chn,int handle, IMPIspOsdAttrAsm *pIspOsdAttr)
{
	int newrectsize = 0,oldrectsize = 0;
	if (handle >= MAXISPOSDPIC || handle < 0) {
		IMP_LOG_ERR(TAG, "[%s][%d] ISPOSD Invalidate handle(%d)\n", __func__,__LINE__,handle);
		return -1;
	}
	if (chn < 0 || chn > 1) {
		IMP_LOG_ERR(TAG, "[%s][%d]  chn%d is invalid\n", __func__, __LINE__, chn);
		return -1;
	}
	if (NULL == pIspOsdAttr) {
		IMP_LOG_ERR(TAG, "[%s][%d] prAttr Invalidate param\n", __func__,__LINE__);
		return -1;
	}
#if 1
	/*边界判断，若OSD超出屏幕边界，则修改跨度*/
	int ret = 0;
	uint32_t width = 0, height = 0;
	uint16_t top = 0, left = 0, osdw = 0, osdh = 0;
	IMPFrameInfo frame = {0};

	if(0 == chn) {
		ret = fsgetframeparam(chn, &frame);
		if(ret < 0) {
			IMP_LOG_ERR(TAG, "[%s][%d]  get frame param err\n", __func__, __LINE__);
			return -1;
		}
	} else if(1 == chn){
		ret = fsgetframeparam(chn + 2, &frame);
		if(ret < 0) {
			IMP_LOG_ERR(TAG, "[%s][%d]  get frame param err\n", __func__, __LINE__);
			return -1;
		}
	}

	width  = frame.width;
	height = frame.height;
	top  = pIspOsdAttr->stsinglepicAttr.pic.osd_top;
	left = pIspOsdAttr->stsinglepicAttr.pic.osd_left;
	osdw = pIspOsdAttr->stsinglepicAttr.pic.osd_width;
	osdh = pIspOsdAttr->stsinglepicAttr.pic.osd_height;
	if((top + osdh) > height || (left + osdw > width) ) {
		IMP_LOG_ERR(TAG, "[%s][%d]  WRNING!!!(top:%d+osdh:%d)=(%d) (left:%d+osdw:%d)=(%d) frame(w:%d,h:%d)\n", __func__, __LINE__,\
			top, osdh, (top+osdh), left, osdw, (left+osdw), width, height);
		return -1;
	}
#endif
	void *pData = NULL;
	IMPIspOsdAttrAsm *pOriIspOsdAttr = NULL;
	IMPISPOSD *pIsposd = getIspOsd();
	if(NULL == pIsposd){
		IMP_LOG_ERR(TAG, "[%s][%d], pIsposd is null,resource has been destroyed\n", __func__,__LINE__);
		return -1;
	}
	if (pIsposd->IspOsdChn[chn].IspOsdNode[handle].status == IMP_ISP_OSD_RGN_FREE) {
		IMP_LOG_ERR(TAG, "%s, the chn%d region %d hasn't been created\n", __func__,chn,handle);
		return -1;
	}
#ifdef ISPOSDPRINT
	struct timeval time;
	int ms_0 = 0,ms_1 = 0;
	gettimeofday(&time,NULL);
	ms_0 = time.tv_sec * 1000 + time.tv_usec / 1000;
#endif
	sem_wait(&pIsposd->semIspRgn);

	pOriIspOsdAttr = &pIsposd->IspOsdChn[chn].IspOsdNode[handle].stIspOsdAsm;/*找到对应通道的对应节点*/
	//根据外部传入参数计算要申请的rmem大小
	oldrectsize = pOriIspOsdAttr->stsinglepicAttr.pic.osd_stride*pOriIspOsdAttr->stsinglepicAttr.pic.osd_height;
	if((newrectsize = IspOsd_rgnsize(pIspOsdAttr)) <= 0){
		IMP_LOG_ERR(TAG, "%s,%d:malloc pData size=%d failed\n", __func__, __LINE__, newrectsize);
		sem_post(&pIsposd->semIspRgn);
		return -1;
	}
	if(ISP_OSD_REG_PIC == pIspOsdAttr->type) {
		/*区域大小改变时，若该区域第一次创建，则分配rmem*/
		if ((oldrectsize != newrectsize)&&(0 == oldrectsize)) {
			if ((pData = OSD_mem_alloc(pIsposd->isp_osd_mem, newrectsize)) == NULL) {
			    IMP_LOG_ERR(TAG, "%s,%d:chn%d handle%d malloc pData size=%d failed\n", __func__, __LINE__,chn,handle,newrectsize);
				sem_post(&pIsposd->semIspRgn);
				return -1;
			}
		} else if (oldrectsize == newrectsize) {
			pData = pOriIspOsdAttr->stsinglepicAttr.pic.osd_image;
		} else {
			IMP_LOG_ERR(TAG, "%s, the chn%d region %d not support changed pic size dynamic,should destroy rgn and recreate\n", __func__,chn,handle);
			sem_post(&pIsposd->semIspRgn);
			return -1;
		}
	} else {
		IMP_LOG_ERR(TAG, "%s, the chn%d region %d OSD type(%d) isn't ISP_OSD_REG_PIC\n", __func__,chn,handle,pIspOsdAttr->type);
		sem_post(&pIsposd->semIspRgn);
		return -1;
	}

	/*拷贝节点参数*/
	memcpy(pOriIspOsdAttr, pIspOsdAttr, sizeof(IMPIspOsdAttrAsm));

	/*用户地址空间内容拷贝到rmem中,这样即使用户空间释放内存，也不会影响SDK*/
	if(pIspOsdAttr->stsinglepicAttr.pic.osd_image){
		memcpy(pData,pIspOsdAttr->stsinglepicAttr.pic.osd_image,newrectsize);
	} else {
		memset(pData,0,newrectsize);
	}

	pOriIspOsdAttr->stsinglepicAttr.pic.osd_enable = 0;//设置后不生效，需要再显示调用show接口(show接口中存在相交判定操作)
	pOriIspOsdAttr->stsinglepicAttr.pic.osd_image = pData;

	/*地址回溯整理，只有在ISP_OSD_REG_PIC模式下进行整理操作，最外层已经加了,故这里不再加锁*/
	/*对应rmem的内存节点已经发生变化，需要对两条链表上的节点进行地址回溯修改*/
	if (ISP_OSD_REG_PIC == pIspOsdAttr->type) {
        if(pIsposd->isp_osd_mem->brmemsetbak){
			//地址回溯整理
			ISPOSD_RmemSetNewAddr(pIsposd->IspOsdChn[0].busyrlist.head,pIsposd->isp_osd_mem->busy.head);
			ISPOSD_RmemSetNewAddr(pIsposd->IspOsdChn[1].busyrlist.head,pIsposd->isp_osd_mem->busy.head);
            OsdnotifyIsp(pIsposd->IspOsdChn[0].busyrlist.head);
            OsdnotifyIsp(pIsposd->IspOsdChn[1].busyrlist.head);
            pIsposd->isp_osd_mem->brmemsetbak = 0;
        }
	}
#ifdef ISPOSDPRINT
	gettimeofday(&time,NULL);
	ms_1 = time.tv_sec * 1000 + time.tv_usec / 1000;
	IMP_LOG_ERR(TAG, "[%s][%d]	1 IMP_OSD_SetRgnAttr_PicISP,chn%d, handle%d,poldaddr:%p,pnewaddr:%p,costtime:%dms\n", __func__, __LINE__, chn,handle,pData,
	pOriIspOsdAttr->stsinglepicAttr.pic.osd_image,ms_1-ms_0);
#endif
	//IMP_LOG_DBG(TAG, "[%s][%d] chn%d handle%d\n", __func__,__LINE__,chn,handle);

	sem_post(&pIsposd->semIspRgn);

	return 0;
}

int IMP_OSD_GetRgnAttr_ISPPic(int chn,int handle, IMPIspOsdAttrAsm *pIspOsdAttr)
{
	IMP_LOG_DBG(TAG, "[%s][%d] chn%d handle%d\n", __func__,__LINE__,chn,handle);
	if (handle >= MAXISPOSDPIC || handle < 0) {
		IMP_LOG_ERR(TAG, "[%s][%d] ISPOSD Invalidate handle(%d)\n", __func__,__LINE__,handle);
		return -1;
	}
	if (chn < 0 || chn > 1) {
		IMP_LOG_ERR(TAG, "[%s][%d]  chn is invalid\n", __func__, __LINE__, chn);
		return -1;
	}
	if (NULL == pIspOsdAttr) {
		IMP_LOG_ERR(TAG, "[%s][%d] prAttr Invalidate param\n", __func__,__LINE__);
		return -1;
	}
	IMPIspOsdAttrAsm *pOriIspOsdAttr = NULL;
	IMPISPOSD *pIsposd = getIspOsd();
	pOriIspOsdAttr = &pIsposd->IspOsdChn[chn].IspOsdNode[handle].stIspOsdAsm;/*找到对应通道的对应节点*/
	memcpy(pIspOsdAttr,pOriIspOsdAttr,sizeof(IMPIspOsdAttrAsm));
	return 0;
}

int ispointinrect(uint16_t src_startx,uint16_t src_starty,uint16_t srcw,uint16_t srch,uint16_t dst_startx,uint16_t dst_starty)
{
	int ret = 0;
	if( (src_startx <= dst_startx)&&( dst_startx < (src_startx + srcw)) && (src_starty <= dst_starty)&&(dst_starty < (src_starty + srch)) ) {
		ret = 1;
	}
	return ret;
}
/* (minx,miny) ------------
	           |          |
		       ------------(maxx,maxy)
*/
int iscrossrect(uint16_t minx1,uint16_t miny1,uint16_t maxx1,uint16_t maxy1,uint16_t minx2,uint16_t miny2,uint16_t maxx2,uint16_t maxy2)
{
	uint16_t minx = 0,miny = 0,maxx = 0,maxy = 0;
	minx = ISPOSDMAX(minx1,minx2);
	miny = ISPOSDMAX(miny1,miny2);
	maxx = ISPOSDMIN(maxx1,maxx2);
	maxy = ISPOSDMIN(maxy1,maxy2);
	if(minx < maxx && miny < maxy){
		//相交返回1
		return 1;
	}
	return 0;
}
void IspOsdAdjust_Pic(int chn,IMPIspOsdRgnList *pIspRgnList)
{
	if(NULL == pIspRgnList) {
		IMP_LOG_ERR(TAG, "[%s][%d]pIspRgnList is null,check!\n", __func__, __LINE__);
		return;
	}
	IMPISPOSDNode *phead = NULL,*pnode = NULL;
	uint16_t srcw = 0,srch = 0,src_startx = 0,src_starty = 0;
	uint16_t dstw = 0,dsth = 0,dst_startx = 0,dst_starty = 0;
	phead = pIspRgnList->head;
	while(phead) {
		if(phead->stIspOsdAsm.stsinglepicAttr.pic.osd_enable) {
			srcw = phead->stIspOsdAsm.stsinglepicAttr.pic.osd_width;
			srch = phead->stIspOsdAsm.stsinglepicAttr.pic.osd_height;
			src_startx = phead->stIspOsdAsm.stsinglepicAttr.pic.osd_left;
			src_starty = phead->stIspOsdAsm.stsinglepicAttr.pic.osd_top;
		}
		pnode = phead->next;
		while(pnode) {
			if(pnode->stIspOsdAsm.stsinglepicAttr.pic.osd_enable) {
				dstw = pnode->stIspOsdAsm.stsinglepicAttr.pic.osd_width;
				dsth = pnode->stIspOsdAsm.stsinglepicAttr.pic.osd_height;
				dst_startx = pnode->stIspOsdAsm.stsinglepicAttr.pic.osd_left;
				dst_starty = pnode->stIspOsdAsm.stsinglepicAttr.pic.osd_top;
				/*判断若相交，则链表靠后的节点对应的使能开关关闭，否则会产生乱码问题*/
				if(iscrossrect(src_startx,src_starty,src_startx+srcw,src_starty+srch,dst_startx,dst_starty,dst_startx+dstw,dst_starty+dsth))
				{
					IMP_LOG_ERR(TAG,"hand%d has changed showflg,positon(%d,%d)(w,h)(%d,%d)\n",pnode->rAttrIndex,pnode->stIspOsdAsm.stsinglepicAttr.pic.osd_left,
					pnode->stIspOsdAsm.stsinglepicAttr.pic.osd_top,pnode->stIspOsdAsm.stsinglepicAttr.pic.osd_width,
					pnode->stIspOsdAsm.stsinglepicAttr.pic.osd_height);
					pnode->stIspOsdAsm.stsinglepicAttr.pic.osd_enable = 0;//若相交，则关闭相交的块
					pnode->oldshowflg = 0;
				}
			}
			pnode = pnode->next;
		}
		phead = phead->next;

	}
	return ;
}

int IMP_OSD_ShowRgn_ISP(int chn,int handle, int showFlag)
{
	if (handle >= MAXISPOSDPIC || handle < 0) {
		IMP_LOG_ERR(TAG, "[%s][%d] ISPOSD Invalidate handle(%d)\n", __func__,__LINE__,handle);
		return -1;
	}
	if (chn < 0 || chn > 1) {
		IMP_LOG_ERR(TAG, "[%s][%d]	chn is invalid\n", __func__, __LINE__, chn);
		return -1;
	}
	//int ret = 0;
	//void *paddr = NULL,*vaddr = NULL;
	IMPISPOSDNode *pIspOsdNode = NULL;
	IMPISPOSD *pIsposd = getIspOsd();
	if(NULL == pIsposd) {
		IMP_LOG_ERR(TAG, "[%s][%d], pIsposd is null,resource has been destroyed\n", __func__,__LINE__);
		return -1;
	}
	pIspOsdNode = &pIsposd->IspOsdChn[chn].IspOsdNode[handle];

	if (pIspOsdNode->status == IMP_ISP_OSD_RGN_FREE) {
		IMP_LOG_ERR(TAG, "[%s][%d]	rgn is free,can't set showflag\n", __func__, __LINE__, chn);
		return -1;
	}
	sem_wait(&pIsposd->semIspRgn);
	pIspOsdNode->stIspOsdAsm.stsinglepicAttr.pic.osd_enable = showFlag;/*虽然这里设置了，但ISP不知道，还必须要再设置一次*/
	pIspOsdNode->oldshowflg = showFlag;

	/*调整位置：因为ISP硬件资源对重叠区域没有做好处理，导致相交、覆盖的osd出现乱码，断流，因此需要软件做出处理，避免断流情况发生*/
	IspOsdAdjust_Pic(chn,&pIsposd->IspOsdChn[chn].busyrlist);
	OsdnotifyIsp(pIsposd->IspOsdChn[chn].busyrlist.head);
	//OsdnotifyIsp(pIsposd->IspOsdChn[1].busyrlist.head);

#ifdef ISPOSDDBG
	IMPISPOSDNode *phead = pIsposd->IspOsdChn[chn].busyrlist.head;
	while(phead){
		IMP_LOG_ERR(TAG,"chn%d handle%d size:%d (oldshowflg:%d,showflg:%d),positon(%d,%d),(w,h)=(%d,%d)\n",chn,phead->rAttrIndex,
			phead->stIspOsdAsm.stsinglepicAttr.pic.osd_height*phead->stIspOsdAsm.stsinglepicAttr.pic.osd_stride,
			phead->oldshowflg,phead->stIspOsdAsm.stsinglepicAttr.pic.osd_enable,
			phead->stIspOsdAsm.stsinglepicAttr.pic.osd_left,phead->stIspOsdAsm.stsinglepicAttr.pic.osd_top,
			phead->stIspOsdAsm.stsinglepicAttr.pic.osd_width,phead->stIspOsdAsm.stsinglepicAttr.pic.osd_height);
		phead = phead->next;
	}
#endif
	//IMP_LOG_DBG(TAG, "[%s][%d] handle%d,showflg%d\n", __func__,__LINE__,handle,showFlag);

	sem_post(&pIsposd->semIspRgn);

	return 0;
}

int IMP_OSD_UpdateRgnAttrData_ISP(int chn,int handle,IMPIspOsdAttrAsm *pIspOsdAttrAsm)
{
#ifdef ISPOSDDBG
	IMP_LOG_ERR(TAG, "[%s][%d]	IMP_OSD_UpdateRgnAttrData_ISP,chn%d, handle%d \n", __func__, __LINE__, chn,handle);
#endif
	if(chn < 0 || chn > 1) {
		IMP_LOG_ERR(TAG, "[%s][%d]	chn is invalid\n", __func__, __LINE__, chn);
		return -1;
	}

	if (handle >= MAXISPOSDPIC || handle < 0) {
		IMP_LOG_ERR(TAG, "[%s][%d] ISPOSD Invalidate handle(%d)\n", __func__,__LINE__,handle);
		return -1;
	}
	if (NULL == pIspOsdAttrAsm) {
		IMP_LOG_ERR(TAG, "[%s][%d] ISPOSD Invalidate pIspOsdAttrAsme\n", __func__,__LINE__);
		return -1;
	}
	int ret = 0;
	void *paddr = NULL,*vaddr = NULL;
	int newrectsize = 0,oldrectsize = 0;
	IMPISPOSD *pIsposd = getIspOsd();
	if(NULL == pIsposd) {
		IMP_LOG_ERR(TAG, "[%s][%d], pIsposd is null,resource has been destroyed\n", __func__,__LINE__);
		return -1;
	}
	IMPISPOSDNode *pIspOsdNode = &pIsposd->IspOsdChn[chn].IspOsdNode[handle];

	if (pIspOsdNode->status == IMP_ISP_OSD_RGN_FREE) {
		IMP_LOG_ERR(TAG, "[%s][%d]	rgn is free,can't set showflag\n", __func__, __LINE__, chn);
		return -1;
	}
	sem_wait(&pIsposd->semIspRgn);

	oldrectsize = pIspOsdNode->stIspOsdAsm.stsinglepicAttr.pic.osd_height * pIspOsdNode->stIspOsdAsm.stsinglepicAttr.pic.osd_stride;

	if((newrectsize = IspOsd_rgnsize(pIspOsdAttrAsm)) < 0){
		IMP_LOG_ERR(TAG, "%s,%d:malloc pData size=%d failed\n", __func__, __LINE__, newrectsize);
		sem_post(&pIsposd->semIspRgn);
		return -1;
	}

	if(oldrectsize != newrectsize){
		IMP_LOG_ERR(TAG, "%s,%d:oldsize(%d) != newsize(%d),can't update\n", __func__, __LINE__, oldrectsize,newrectsize);
		sem_post(&pIsposd->semIspRgn);
		return -1;
	}

	/*1、更新*/
	memcpy(pIspOsdNode->stIspOsdAsm.stsinglepicAttr.pic.osd_image,pIspOsdAttrAsm->stsinglepicAttr.pic.osd_image,newrectsize);

	/*将rmem对应的虚拟地址转成物理地址传给ISP，上层操作仍使用虚拟地址*/
	vaddr = pIspOsdNode->stIspOsdAsm.stsinglepicAttr.pic.osd_image;
	paddr = isposd_mem_vir_to_phy(vaddr);
	//printf("paddr:%#x,osdimage:%#x\n",vaddr,paddr);

	/*1、设置完成后，ISP使用物理地址，后续SDK需要修改成虚拟地址*/
	pIspOsdNode->stIspOsdAsm.stsinglepicAttr.pic.osd_image = paddr;
	ret = IMP_ISP_Tuning_SetOSDAttr(&pIspOsdNode->stIspOsdAsm.stsinglepicAttr);
	if(ret < 0) {
		IMP_LOG_ERR(TAG, "[%s][%d]	IMP_ISP_Tuning_SetOSDAttr err\n", __func__, __LINE__, chn);
		sem_post(&pIsposd->semIspRgn);
		return -1;
	}
	/*2、设置完成后，SDK层仍使用虚拟地址，后续需要ISP提供数据结构中包含虚拟地址和物理地址*/
	pIspOsdNode->stIspOsdAsm.stsinglepicAttr.pic.osd_image = vaddr;
	sem_post(&pIsposd->semIspRgn);

	return 0;
}

int IMP_OSD_DestroyRgn_ISP(int chn,int handle)
{
	if(chn < 0 || chn > 1) {
		IMP_LOG_ERR(TAG, "[%s][%d]	chn is invalid\n", __func__, __LINE__, chn);
		return -1;
	}

	if (handle >= MAXISPOSDPIC || handle < 0) {
		IMP_LOG_ERR(TAG, "[%s][%d] ISPOSD Invalidate handle(%d)\n", __func__,__LINE__,handle);
		return -1;
	}

	int ret = 0;
	IMPISPOSDNode *pIspOsdNode = NULL;
	IMPISPOSD *pIsposd = getIspOsd();
	if(NULL == pIsposd) {
		IMP_LOG_ERR(TAG, "[%s][%d], pIsposd is null,resource has been destroyed\n", __func__,__LINE__);
		return -1;
	}
	pIspOsdNode = &pIsposd->IspOsdChn[chn].IspOsdNode[handle];
    if(pIspOsdNode->stIspOsdAsm.stsinglepicAttr.pic.osd_enable){
        /*若客户调用销毁区域时，没有关闭显示区域，则ISP仍绘制该区域，因此这里需要关闭*/
        IMP_OSD_ShowRgn_ISP(chn,handle,0);
    }

	sem_wait(&pIsposd->semIspRgn);
#ifdef ISPOSDPRINT
	IMP_LOG_ERR(TAG, "[%s][%d]	IMP_OSD_DestroyRgn_ISP,chn%d, handle%d,osd_image:%p\n", __func__, __LINE__, chn,handle,pIspOsdNode->stIspOsdAsm.stsinglepicAttr.pic.osd_image);
#endif
	if (pIsposd->IspOsdChn[chn].IspOsdNode[handle].status == IMP_ISP_OSD_RGN_BUSY && (pIsposd->IspOsdChn[chn].IspOsdNode[handle].refcnt == 1))
	{
		if (pIspOsdNode != pIsposd->IspOsdChn[chn].busyrlist.head && pIspOsdNode != pIsposd->IspOsdChn[chn].busyrlist.tail) {
			pIspOsdNode->prev->next = pIspOsdNode->next;
			pIspOsdNode->next->prev = pIspOsdNode->prev;
		} else if ((pIspOsdNode == pIsposd->IspOsdChn[chn].busyrlist.head) && (pIspOsdNode == pIsposd->IspOsdChn[chn].busyrlist.tail)) {
			pIsposd->IspOsdChn[chn].busyrlist.head = pIsposd->IspOsdChn[chn].busyrlist.tail = NULL;
		} else if ((pIspOsdNode == pIsposd->IspOsdChn[chn].busyrlist.head) && (pIspOsdNode != pIsposd->IspOsdChn[chn].busyrlist.tail)) {
			pIsposd->IspOsdChn[chn].busyrlist.head = pIsposd->IspOsdChn[chn].busyrlist.head->next;
			pIsposd->IspOsdChn[chn].busyrlist.head->prev = NULL;
		} else if ((pIspOsdNode != pIsposd->IspOsdChn[chn].busyrlist.head) && (pIspOsdNode == pIsposd->IspOsdChn[chn].busyrlist.tail)) {
			pIsposd->IspOsdChn[chn].busyrlist.tail = pIsposd->IspOsdChn[chn].busyrlist.tail->prev;
			pIsposd->IspOsdChn[chn].busyrlist.tail->next = NULL;
		}

		if (pIsposd->IspOsdChn[chn].freerlist.head == NULL) {
			pIsposd->IspOsdChn[chn].freerlist.head = pIsposd->IspOsdChn[chn].freerlist.tail = pIspOsdNode;
			pIsposd->IspOsdChn[chn].freerlist.tail->prev = NULL;
			pIsposd->IspOsdChn[chn].freerlist.tail->next = NULL;
		} else {
			pIsposd->IspOsdChn[chn].freerlist.tail->next = pIspOsdNode;
			pIsposd->IspOsdChn[chn].freerlist.tail->next->prev = pIsposd->IspOsdChn[chn].freerlist.tail;
			pIsposd->IspOsdChn[chn].freerlist.tail = pIsposd->IspOsdChn[chn].freerlist.tail->next;
			pIsposd->IspOsdChn[chn].freerlist.tail->next = NULL;
		}
		pIsposd->IspOsdChn[chn].IspOsdNode[handle].status = IMP_ISP_OSD_RGN_FREE;
		pIsposd->IspOsdChn[chn].IspOsdNode[handle].refcnt -= 1;

		if (pIspOsdNode->stIspOsdAsm.stsinglepicAttr.pic.osd_image != NULL) {
			ret = OSD_mem_free(pIsposd->isp_osd_mem, pIspOsdNode->stIspOsdAsm.stsinglepicAttr.pic.osd_image);
			if(ret < 0) {
				sem_post(&pIsposd->semIspRgn);
				IMP_LOG_ERR(TAG, "[%s][%d]OSD_mem_free err\n", __func__,__LINE__);
				return -1;
			}
			//OSD_mem_dump(osd->osd_mem);
		}
		memset(&pIspOsdNode->stIspOsdAsm, 0, sizeof(IMPIspOsdAttrAsm));
	}

	sem_post(&pIsposd->semIspRgn);
	IMP_LOG_DBG(TAG, "[%s][%d] chn%d handle%d\n", __func__,__LINE__,chn,handle);

	return 0;
}

/*统一命名格式，提供给客户较为规范的接口*/
int IMP_ISP_Tuning_SetOsdPoolSize(int size)
{
	return IMP_OSD_SetPoolSize_ISP(size);
}

int IMP_ISP_Tuning_CreateOsdRgn(int chn,IMPIspOsdAttrAsm *pIspOsdAttr)
{
	return IMP_OSD_CreateRgn_ISP(chn, pIspOsdAttr);
}

int IMP_ISP_Tuning_SetOsdRgnAttr(int chn,int handle, IMPIspOsdAttrAsm *pIspOsdAttr)
{
	return IMP_OSD_SetRgnAttr_PicISP(chn, handle, pIspOsdAttr);
}

int IMP_ISP_Tuning_GetOsdRgnAttr(int chn, int handle, IMPIspOsdAttrAsm *pIspOsdAttr)
{
	return IMP_OSD_GetRgnAttr_ISPPic(chn, handle, pIspOsdAttr);
}

int IMP_ISP_Tuning_ShowOsdRgn(int chn, int handle, int showFlag)
{
	return IMP_OSD_ShowRgn_ISP(chn, handle, showFlag);
}

int IMP_ISP_Tuning_DestroyOsdRgn(int chn, int handle)
{
	return IMP_OSD_DestroyRgn_ISP(chn,handle);
}
